﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.Serialization;

namespace MPCR.Tree.Tree
{
    /// <summary>
    /// 自定义TreeViewItemModel可以把一个继承了ATreeViewItemModel类的普通实体包装称一个TreeViewItem节点。
    /// </summary>
    [DataContract]
    public class TreeViewItemModel : Observable
    {
        TreeViewItemModel parent;

        private ATreeViewItemModel source;
        /// <summary>
        /// 获得原始实体类型，可以直接进行强制类型转换得到原始值。
        /// </summary>
        public ATreeViewItemModel Source
        {
            get { return source; }
        }


        /// <summary>
        /// 通过parent和t本身创建一个节点，并同时把该节点的父节点指向parent。
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="t"></param>
        public TreeViewItemModel(TreeViewItemModel parent, ATreeViewItemModel t)
            : this(t)
        {
            if (parent==null||t == null)
            {
                throw new ArgumentNullException("parameter can not be null!");
            }
            this.parent = parent;
            if (this.parent != null)
            {
                this.parent.Children.Add(this);
                if (this.parent.isChecked == true)
                {
                    this.isChecked = true;
                    this.parent.checkedChildren.Add(this);
                }
            }
        }

        /// <summary>
        /// 通过一个ITreeViewItemModel类型实例创建一个节点对象。
        /// </summary>
        /// <param name="t"></param>
        private TreeViewItemModel(ATreeViewItemModel t)
        {
            this.isChecked = null;
            this.children = new ObservableCollection<TreeViewItemModel>();
            this.checkedChildren = new ObservableCollection<TreeViewItemModel>();
            this.source = t;
            this.isChecked = false;
        }

        /// <summary>
        /// 父节点
        /// </summary>
        public TreeViewItemModel Parent
        {
            get { return parent; }
            set
            {
                parent = value;
                this.NotifyPropertyChanged("Parent");
            }
        }

        ObservableCollection<TreeViewItemModel> children;

        /// <summary>
        /// 孩子节点
        /// </summary>
        public ObservableCollection<TreeViewItemModel> Children
        {
            get { return children; }
            set
            {
                children = value;
                this.NotifyPropertyChanged("Children");
            }
        }
        bool isSelected;

        /// <summary>
        /// 是否选中
        /// </summary>
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;
                this.NotifyPropertyChanged("IsSelected");
            }
        }
        bool isInList;

        /// <summary>
        /// 是否在列表中
        /// </summary>
        public bool IsInList
        {
            get { return isInList; }
            set
            {
                isInList = value;
                this.NotifyPropertyChanged("IsInList");
            }
        }
        bool isLeaf;

        /// <summary>
        /// 是否叶子节点
        /// </summary>
        public bool IsLeaf
        {
            get { return isLeaf; }
            set
            {
                isLeaf = value;
                this.NotifyPropertyChanged("IsLeaf");
            }
        }
        bool? isChecked = false;

        /// <summary>
        /// 是否被勾选
        /// </summary>
        public bool? IsChecked
        {
            get { return isChecked; }
            set
            {
                isChecked = value;
                this.NotifyPropertyChanged("IsChecked");
                this.NotifyParentChecked();
                this.CheckChildren(value);
            }
        }
        private void CheckChildren(bool? value)
        {
            if (null == value || children == null || children.Count == 0)
            {
                return;
            }
            if (value==true)
            {
                foreach (TreeViewItemModel child in children)
                {
                    child.isChecked = true;
                    child.NotifyPropertyChanged("IsChecked");
                    if (child.isLeaf == false)
                    {
                        child.CheckChildren(value);
                    }
                    if (!this.CheckedChildren.Contains(child))
                    {
                        this.CheckedChildren.Add(child); 
                    }
                }
            }
            else
            {
                foreach (TreeViewItemModel child in children)
                {
                    child.isChecked = false;
                    child.NotifyPropertyChanged("IsChecked");
                    if (child.isLeaf == false)
                    {
                        child.CheckChildren(value);
                    }
                    if (this.CheckedChildren.Contains(child))
                    {
                        this.CheckedChildren.Remove(child);
                    }
                }
            }
            
        }

        /// <summary>
        /// 通知父节点
        /// </summary>
        /// <param name="child"></param>
        void NotifyParentChecked()
        {
            if (parent == null)
            {
                return;
            }
            if (this.isChecked == false)
            {
                if(parent.CheckedChildren.Contains(this))
                parent.CheckedChildren.Remove(this);
            }
            else
            {
                if (!parent.CheckedChildren.Contains(this))
                    parent.CheckedChildren.Add(this);
            }
            bool? check = this.parent.isChecked;
            if (this.parent.CheckedChildren.Count == 0)
            {
                check = false;
            }
            else if(this.parent.CheckedChildren.Count==this.parent.Children.Count)
            {
                check = true;
            }
            else
            {
                check = null;
            }

            if (this.parent.isChecked != check)
            {

                if (this.parent != null)
                {
                    this.parent.isChecked = check;
                    this.parent.NotifyPropertyChanged("IsChecked");
                    this.parent.NotifyParentChecked();

                }
            }
        }

        ObservableCollection<TreeViewItemModel> checkedChildren;

        /// <summary>
        /// 当前被勾选的所有直接孩子节点
        /// </summary>
        public ObservableCollection<TreeViewItemModel> CheckedChildren
        {
            get { return checkedChildren; }
            set { checkedChildren = value; }
        }

        private bool isExpanded;

        public bool IsExpanded
        {
            get { return isExpanded; }
            set
            {
                isExpanded = value;
                this.NotifyPropertyChanged("IsExpanded");
                this.NotifyParentIsExpanded();
            }
        }

        void NotifyParentIsExpanded()
        {
            if (this.isExpanded == true)
            {
                if (this.parent != null)
                {
                    this.parent.IsExpanded = true;
                    this.IsSelected = true;
                }
            }
        }

        public static TreeViewItemModel GetDefaultTreeViewItemModelRoot() 
        {
            return new TreeViewItemModel(new DefaultTreeViewModelRoot());
        }
        private class DefaultTreeViewModelRoot : ATreeViewItemModel
        {

        }
    }

    /// <summary>
    /// 为树节点添加显示文本值属性。
    /// </summary>
    [DataContract]
    public class ATreeViewItemModel : Observable
    {
        private String treeViewItemText;

        [DataMember]
        public virtual String TreeViewItemText
        {
            get { return treeViewItemText; }
            set { treeViewItemText = value; this.NotifyPropertyChanged("TreeViewItemText"); }
        }
    }
    /// <summary>
    /// 属性值修改可被观察到得抽象类。
    /// </summary>
    [DataContract]    
    public abstract class Observable : INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;

        protected virtual void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    
}
